﻿using App.DbInterfaces;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Reflection;
using DbType = SqlSugar.DbType;

namespace App.SqlSugar
{
    public static class SqlSugarExtension
    {

        public static SqlSugarScope GetSqlSugarConfig(DbType dbType, string mySqlDns, Type modelType,
            Action<string>? sqlLog = null, Action<double, string, string>? warnSqlLog = null,
             Action<string>? errorSqlLog = null
            )
        {
            var sqlSugar = new SqlSugarScope(new ConnectionConfig()
            {
                DbType = dbType,
                ConnectionString = mySqlDns,
                IsAutoCloseConnection = true,   //是否自动关闭数据库
                ConfigureExternalServices = new ConfigureExternalServices
                {
                    // 表名不做处理
                    EntityNameService = SqlSugarHelp.table,
                    // 列名
                    EntityService = SqlSugarHelp.column,
                },
            },
             db =>
             {
                 //每次上下文都会执行

                 //Sql超时 2分钟
                 db.Ado.CommandTimeOut = 60 * 2;

                 //全局过滤器
                 db.QueryFilter.AddTableFilter<IIsDelete>(it => it.isDelete == false);

                 //sql执行前
                 db.Aop.OnLogExecuting = (sql, pars) =>
                 {
                     if (sqlLog != null)
                     {
                         sqlLog?.Invoke(sql);
                     }
                 };

                 // 数据curd事件
                 db.Aop.DataExecuting = (oldValue, entityInfo) =>
                 {
                     /*** 列级别事件：插入的每个列都会进事件 ***/
                     var type = entityInfo.OperationType;
                     var fieId = entityInfo.PropertyName.ToLower();

                     // 新增
                     if (type == DataFilterType.InsertByObject)
                     {
                         if (fieId == "createDt".ToLower())
                         {
                             entityInfo.SetValue(DateTime.Now);//修改CreateTime字段
                         }
                         if (fieId == "isDelete".ToLower())
                         {
                             entityInfo.SetValue(false);
                         }
                     }
                     else if (type == DataFilterType.UpdateByObject)
                     {
                         if (fieId == "updateDt".ToLower())
                         {
                             entityInfo.SetValue(DateTime.Now);//修改CreateTime字段
                         }
                     }
                     else if (type == DataFilterType.DeleteByObject)
                     {
                         if (fieId == "isDelete".ToLower())
                         {
                             entityInfo.SetValue(true);
                         }
                     }
                 };

                 //SQL执行完
                 db.Aop.OnLogExecuted = (sql, p) =>
                 {
                     if (warnSqlLog != null)
                     {
                         var timeMill = db.Ado.SqlExecutionTime.TotalMilliseconds;

                         //执行时间超过1秒
                         if (timeMill > 2 * 1000)
                         {
                             //代码CS文件名
                             var fileName = db.Ado.SqlStackTrace.FirstFileName;
                             //代码行数
                             var fileLine = db.Ado.SqlStackTrace.FirstLine;
                             //方法名
                             var firstMethodName = db.Ado.SqlStackTrace.FirstMethodName;

                             //获取上层方法的信息
                             var parentFileName = db.Ado.SqlStackTrace.MyStackTraceList[1].FileName;

                             var sqlStr = string.Format("{0}:【{1}】{2}", fileName, firstMethodName, fileLine);

                             warnSqlLog?.Invoke(timeMill, sqlStr, parentFileName);
                         }
                     }
                 };

                 //SQL报错
                 db.Aop.OnError = (exp) =>
                 {
                     if (errorSqlLog != null)
                     {
                         //获取原生SQL推荐 5.1.4.63  性能OK
                         var sql = UtilMethods.GetNativeSql(exp.Sql, exp.Parametres as SugarParameter[]);

                         errorSqlLog?.Invoke(sql);
                     }
                 };


                 ////迁移表
                 //db.DbMaintenance.CreateDatabase();
                 ////var keys = new List<string>() { "models", "model" };
                 ////var types = modelType.Assembly.GetTypes()
                 ////.Where(p => keys.Any(w => p.FullName.ToLower().Contains(w))).ToArray();
                 //var types = modelType.Assembly.GetTypes();
                 //db.CodeFirst.InitTables(types);//根据types创建表

             });

            return sqlSugar;
        }


        public static void UseSqlSugarExtension(this IServiceCollection services, DbType dbType, string mySqlDns, Type modelType,
            Action<string>? sqlLog, Action<double, string, string>? warnSqlLog,
            Action<string>? errorLog)
        {
            var sqlSugar = GetSqlSugarConfig(dbType, mySqlDns, modelType, sqlLog, warnSqlLog, errorLog);

            services.AddSingleton<ISqlSugarClient>(p => sqlSugar);


            // 注入仓储
            services.UseSqlSugarRegisterExtension();
        }

    }
}
